上篇提到的prettyjson工具,经我改写之后,可以JavaScript对象格式输出缩进排版的JSON格式。如下所示:
var prettyjson = require('prettyjson');
var data = {
username: 'rafeca',
url: 'https://github.com/rafeca',
twitter_account: 'https://twitter.com/rafeca',
projects: ['prettyprint', 'connfu'],
};
console.log(prettyjson.render(data, options));
输出:
{
"username": "rafeca",
"url": "https://github.com/rafeca",
"twitter_account": "https://twitter.com/rafeca",
"projects": [
"prettyprint",
"connfu"
]
}
我不记得这中间遇到多少坑了。
将JSON对象格式化输出大致的思路是利用递归的方式,将中结果保存到数组,然后一次性输出。
1.判断data是否是对象,如果是则保存(push)'当前缩进空格+{',中间结果和'当前缩进空格+{,',将'当前缩进空格+{,'保存到数组(output)前将当前数组(output)的最后一个元素的末尾逗号删除。
- 判断中间结果是否是可以直接序列化的,若是,序列化保存到数组(output)
- 不是则递归下去
if (typeof data === 'object') {
/*一开始时当前缩进为0,所以可以输出最外一层对齐的 { 和 } */
var line = indent(indentation);
output.push(line+'{');
var key;
var isError = data instanceof Error;
indentation = indentation + options.defaultIndentation;
Object.getOwnPropertyNames(data).forEach(function(i) {
// Prepend the index at the beginning of the line
key = ('"' + i +'"'+ ': ');
key = indent(indentation) + key;
// Skip `undefined`, it's not a valid JSON value.
if (data[i] === undefined) {
return;
}
/*可以直接序列化的,拼接到"key": 即可,后面仍有逗号*/
if(isSerializable(data[i])) {
output.push(key + outputData(data[i]) + ',');
}else {
/* 递归,注意render的结果是字符串,开始位置有缩进,
* 所以拼接到key: 后面时需要trim掉
*/
var temp = exports.render(data[i], options, indentation);
output.push(key + temp.trim() + ',');
}
});
removeLastComma(output);
output.push(line + '},');
}
2.判断是否是数组,如果是则保存(push)'当前缩进空格+[',中间结果和'当前缩进空格+],',将'当前缩进空格+],'保存到数组(output)前将当前数组(output)的最后一个元素的末尾逗号删除。
- 判断中间结果是否可以直接序列化,若是,则序列化保存到数组(output)
- 不是则递归下去
if (Array.isArray(data)) {
var line = indent(indentation);
indentation = indentation + options.defaultIndentation;
output.push(line + '[');
// If the array is empty
if (data.length === 0) {
output.push(indent(indentation) +' ');
} else {
data.forEach(function(element) {
/* 可以直接序列化的情况*/
if(isSerializable(element)) {
output.push(indent(indentation) + outputData(element) + ',');
}else {
/* 递归 */
var temp = exports.render(data[i], options, indentation);
output.push(key + temp.trim() + ',');
}
});
removeLastComma(output);
}
output.push(line + '],');
}
3.辅助函数,判断是否可以直接序列化(boolean, number, string, null)
var isSerializable = function(input, onlyPrimitives) {
if (typeof input === 'boolean' ||
typeof input === 'number' || input === null) {
return true;
}
if (typeof input === 'string' && input.indexOf('\n') === -1) {
return true;
}
return false;
};
4.辅助函数,输出字符和其他类型
var outputData = function(input) {
if (typeof input === 'string') {
// Print strings wraped by double quote
return '"' + input + '"';
}
if (input === true) {
return 'true';
}
if (input === false) {
return 'false';
}
if (input === null) {
return '';
}
if (typeof input === 'number') {
return input;
}
return input;
};
5.主函数
exports.render = function(data, options, indentation) {
indentation = indentation || 0;
options = options || {};
options.defaultIndentation = options.defaultIndentation || 2;
var output = []; //合并所有中间结果的数组
removeLastComma(output); //删除最后一个逗号
// Return all the lines as a string
return output.join('\n');
}
6.renderstring函数将字符串反序列成对象然后再调用render方法格式化、序列化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。